
/***
This file includes the implementation of the pf2dot class.
$Id$
*/
#include "pf2dot.h"

#include <iomanip>
#include <strstream>

namespace nm_pslab{

PropVal::PropVal(){
}

std::string PropVal::GenStr()const{
   std::ostringstream oss;
   for(PropVal::const_iterator p_item = begin(); p_item != end(); ++p_item){
      if(p_item != begin()){
	 oss << ", ";
      }
      oss << p_item -> first << " = " << p_item -> second;
   }
   return oss.str();
}

Dot::Dot(bool _dir):m_dir(_dir){
}

Dot& Dot::SetName(const std::string& _name){
   m_name = _name;
   return *this;
}

Dot::Edge& Dot::InsertEdge(const std::string& _nd1_name, const std::string& _nd2_name, const std::string& _e_name){
   m_edge_vec.push_back(Edge(_nd1_name, _nd2_name, _e_name));
   return m_edge_vec.back();
}

Dot::Node& Dot::InsertNode(const std::string& _name){
   m_node_vec.push_back(Node(_name));
   return m_node_vec.back();
}

bool Dot::IsDir()const{
   return m_dir;
}

const std::string& Dot::GetName()const{
   return m_name;
}

std::ostream& Dot::OutputItems(std::ostream& _os_)const{
	for(std::vector<Dot::Node>::const_iterator p_node = m_node_vec.begin();
	  p_node != m_node_vec.end(); ++ p_node){
	   _os_ << *p_node << std::endl;
	}
	for(std::vector<Dot::Edge>::const_iterator p_edge = m_edge_vec.begin();
	  p_edge != m_edge_vec.end(); ++p_edge){
	   _os_ << *p_edge << std::endl;
	}
	return _os_;
}

Dot::Node::Node(const std::string& _name):m_name(_name){
}

Dot::Edge::Edge(const std::string& _nd1_name, const std::string& _nd2_name, const std::string& _e_name)
  : m_name(_e_name), m_nd1_name(_nd1_name), m_nd2_name(_nd2_name){
}

std::ostream& operator << (std::ostream& _os_, const Dot& _dot){
   _os_ << (_dot.IsDir() ? "digraph" : "graph") << " " << _dot.GetName() <<"{" << std::endl;
//   _os_ << "node [color = red, fillcolor = red] " << std::endl;
   _dot.OutputItems(_os_);
   _os_ << "}" << std::endl;
   	
   return _os_;
}

std::ostream& operator << (std::ostream& _os_ , const Dot::Node& _dot_node){
   _os_ << _dot_node.m_name;
   _os_ << ";";
   return _os_;
}

std::ostream& operator << (std::ostream& _os_ , const Dot::Edge& _dot_edge){
   _os_ << _dot_edge.m_nd1_name << "->" <<_dot_edge.m_nd2_name;
   //TODO: "->" should be manipulatable.
//   if(!_dot_edge.m_name.empty()){
      _os_ << "[" << _dot_edge.m_prop_val.GenStr() << ", label=" << '"' << _dot_edge.m_name << '"' << "]";
//   }
   _os_ << ";";
   return _os_;
}

Pf4Dot::Pf4Dot(const std::string& _name):m_name(_name){
}

Pf4Dot::Ln& Pf4Dot::InsertLn(const std::string& _name, const std::string& _ist_name, const std::string& _zst_name,
   double _ip, double _iq, double _zp, double _zq, int _island){
     m_ln_vec.push_back(Ln(_name, _ist_name, _zst_name, _ip, _iq, _zp, _zq, _island));
   return m_ln_vec.back();
}

void Pf4Dot::GenDot(std::ostream& _os_){
   Dot dot(true);
   for(std::vector<Ln>::iterator p_ln = m_ln_vec.begin(); p_ln != m_ln_vec.end(); ++p_ln){
      if(p_ln->m_island > 0){
         dot.InsertEdge(p_ln->m_ist_name, p_ln->m_zst_name, p_ln->GenEdgeLabel()).m_prop_val["color"] = "black";
      }
      else{
	 dot.InsertEdge(p_ln->m_ist_name, p_ln->m_zst_name, std::string()).m_prop_val["style"] = "dotted";
	 /*
	 Dot::Edge& edge = dot.InsertEdge(p_ln->m_ist_name, p_ln->m_zst_name, "");
	 edge.m_prop_val["style"] = "dotted";
	 edge.m_prop_val["color"] = "gray";
	 */
      }
   }
   _os_ << dot;
}

Pf4Dot::Ln::Ln(const std::string& _name, const std::string& _ist_name, const std::string& _zst_name,
  double _ip, double _iq, double _zp, double _zq, int _island)
  : m_name(_name), m_ist_name(_ist_name), m_zst_name(_zst_name), 
  	m_ipower(_iq, _iq), m_zpower(_zp, _zq), m_island(_island){
}

std::string Pf4Dot::Ln::GenEdgeLabel()const{
   std::ostringstream oss;
   oss << std::fixed << std::setprecision(1) << ( m_ipower.real() >= m_zpower.real() ? m_ipower : m_zpower);
   return oss.str();
}

};
